import datetime
import re

relative = re.compile("(?P<sign>[+|-]?)(?P<num>\d+) *(?P<unit>[d|w])")
date     = re.compile("(?P<day>\d+)(/(?P<month>\d+))?(/(?P<year>\d+))?")

def make_date(descr):
    """Make a datetime object from a description. The description can
    either be a date, partially or fully specified, or a relative
    designation.

    The supported syntax for relative designations is very simple:

       [-|+]? N [d|w]

    for in N (d)ays or N (w)eeks. The minus sign indicates prior dates.

    Dates will be specifed by: dd[/mm[/yyyy]] format, with omitted
    parts of the date being replaced by information from the current
    date.

    >>> make_date("01/01/2006")
    datetime.date(2006, 1, 1)

    >>> make_date("5 d") - datetime.date.today()
    datetime.timedelta(5)

    >>> make_date("-2w") - datetime.date.today()
    datetime.timedelta(-14)
    """

    current_date = datetime.date.today()

    match = relative.match(descr)

    new_date = None

    if match:

        days = int(match.group('num'))
        if match.group('unit') == 'w':
            days *= 7

        if match.group('sign') == '-':
            days *= -1

        new_date =  current_date + datetime.timedelta(days)

    else:

        match = date.match(descr)

        if match:

            day   = match.group('day')
            month = match.group('month') or current_date.month
            year  = match.group('year')  or current_date.year

            new_date = current_date.replace(day=int(day), month=int(month), year=int(year))

    return new_date
    
if __name__=="__main__":

    import doctest
    import Findtime
    doctest.testmod(Findtime)
